package rs.etf.es.visualization;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;

import rs.etf.es.algorithm.Instantiation;
import rs.etf.es.algorithm.JTextAreaLogger;
import rs.etf.es.algorithm.Node;
import rs.etf.es.algorithm.NodeAddressBook;
import rs.etf.es.algorithm.RequestManager;

public class InstantiationDialog extends JDialog {

    private static final int NO_SELECTION = -1;

    private final JPanel contentPanel = new JPanel();
    private JTextArea txtAlreadyInstantiated;
    private JPanel pnlAlreadyInstantiated;
    private JList<String> lstVariable;
    private JButton btnAddInstantiation;
    private JPanel pnlVariables;
    private JList<String> lstValues;

    private JScrollPane scrollPane_1;

    private ArrayList<Instantiation> instantiatedNow = new ArrayList<Instantiation>();

    DefaultListModel<String> valuesModel = new DefaultListModel<String>();
    DefaultListModel<String> variablesModel = new DefaultListModel<String>();

    /**
     * Create the dialog.
     */
    public InstantiationDialog() {
	setIconImage(Toolkit.getDefaultToolkit().getImage(InstantiationDialog.class.getResource("/images/star.png")));
	setModal(true);
	setTitle("Instantiation Dialog");
	setBounds(100, 100, 443, 292);
	getContentPane().setLayout(new BorderLayout());
	contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
	getContentPane().add(contentPanel, BorderLayout.CENTER);
	contentPanel.setLayout(null);

	pnlAlreadyInstantiated = new JPanel();
	pnlAlreadyInstantiated.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "Already Instantiated", TitledBorder.LEADING, TitledBorder.TOP, null, null));
	pnlAlreadyInstantiated.setBounds(10, 11, 187, 168);
	contentPanel.add(pnlAlreadyInstantiated);
	pnlAlreadyInstantiated.setLayout(null);

	JScrollPane scrollPane = new JScrollPane();
	scrollPane.setBounds(0, 0, 187, 168);
	pnlAlreadyInstantiated.add(scrollPane);

	txtAlreadyInstantiated = new JTextArea();
	scrollPane.setViewportView(txtAlreadyInstantiated);

	pnlVariables = new JPanel();
	pnlVariables.setBorder(new TitledBorder(null, "Variables", TitledBorder.LEADING, TitledBorder.TOP, null, null));
	pnlVariables.setBounds(265, 11, 152, 95);
	contentPanel.add(pnlVariables);
	pnlVariables.setLayout(null);

	lstVariable = new JList<String>();
	lstVariable.setBorder(new TitledBorder(null, "Variables", TitledBorder.LEADING, TitledBorder.TOP, null, null));
	lstVariable.setBounds(0, 0, 152, 95);
	pnlVariables.add(lstVariable);

	scrollPane_1 = new JScrollPane();
	scrollPane_1.setBounds(265, 117, 152, 93);
	contentPanel.add(scrollPane_1);

	lstValues = new JList<String>();
	scrollPane_1.setViewportView(lstValues);
	lstValues.setBorder(new TitledBorder(null, "Values", TitledBorder.LEADING, TitledBorder.TOP, null, null));

	btnAddInstantiation = new JButton("<");
	btnAddInstantiation.addActionListener(new ActionListener() {
	    public void actionPerformed(ActionEvent e) {
		instantiatedClicked();
	    }
	});
	btnAddInstantiation.setFont(new Font("Tahoma", Font.BOLD, 17));
	btnAddInstantiation.setBounds(206, 68, 49, 43);
	contentPanel.add(btnAddInstantiation);
	{
	    JPanel buttonPane = new JPanel();
	    buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
	    getContentPane().add(buttonPane, BorderLayout.SOUTH);
	    {
		JButton okButton = new JButton("OK");
		okButton.addActionListener(new ActionListener() {
		    public void actionPerformed(ActionEvent e) {
			instaniationFinished();
		    }
		});
		okButton.setActionCommand("OK");
		buttonPane.add(okButton);
		getRootPane().setDefaultButton(okButton);
	    }
	}

    }

    public void setVisible(boolean display) {
	if (display) {
	    initData();
	} else {
	    valuesModel.clear();
	    variablesModel.clear();
	}
	super.setVisible(display);
    }

    public void initData() {
	lstVariable.setModel(variablesModel);
	lstValues.setModel(valuesModel);

	fillInstantiatedVariables();
	fillUninstantiatedVariables(variablesModel);
	VariableSelectedClickHandler clickOnVariable = new VariableSelectedClickHandler(variablesModel, lstVariable, valuesModel);
	clickOnVariable.addClickHandler();

    }

    private void fillInstantiatedVariables() {
	txtAlreadyInstantiated.setText("");
	StringBuilder outputText = new StringBuilder();
	for (Instantiation i : RequestManager.instance().getAlreadyInstantiated()) {
	    outputText.append(i.getVariableName());
	    outputText.append("->");
	    outputText.append(i.getVariableValue());
	    outputText.append("\n");
	}

	for (Instantiation i : RequestManager.instance().getToBeInstantiated()) {
	    outputText.append(i.getVariableName());
	    outputText.append("->");
	    outputText.append(i.getVariableValue());
	    outputText.append(" (-)");
	    outputText.append("\n");
	}

	txtAlreadyInstantiated.setText(outputText.toString());
    }

    private void fillUninstantiatedVariables(DefaultListModel<String> model) {

	for (Node i : NodeAddressBook.instance().getAllNodes()) {
	    if (!RequestManager.instance().isNodeInRequest(i)) {
		model.add(0, i.getName());
	    }
	}
    }

    private void instantiatedClicked() {
	int index = lstVariable.getSelectedIndex();
	if (index == NO_SELECTION) {
	    return;
	}
	String nodeName = variablesModel.getElementAt(index);
	Node selectedNode = NodeAddressBook.instance().getNodeForName(nodeName);
	index = lstValues.getSelectedIndex();
	if (index == NO_SELECTION) {
	    return;
	}
	String valueName = valuesModel.getElementAt(index);
	if (checkIfVariableContainsValue(selectedNode, valueName)) {
	    if (!checkIfAlreadyInstantiated(selectedNode)) {
		txtAlreadyInstantiated.append(selectedNode.getName() + "->" + valueName + "\n");
		instantiatedNow.add(new Instantiation(selectedNode.getName(), valueName));
	    }
	}
    }

    private boolean checkIfVariableContainsValue(Node variable, String value) {
	for (String i : variable.getValues()) {
	    if (value.equals(i)) {
		return true;
	    }
	}

	return false;
    }

    private boolean checkIfAlreadyInstantiated(Node variable) {
	for (Instantiation i : instantiatedNow) {
	    if (i.getVariableName().equals(variable.getName())) {
		return true;
	    }
	}

	return false;
    }

    private void instaniationFinished() {

	StringBuilder builder = new StringBuilder("Instantiated variables: ");
	boolean instantiationExist = false;

	for (Instantiation i : instantiatedNow) {
	    instantiationExist = true;
	    builder.append(i.getVariableName());
	    builder.append(" for ");
	    builder.append(i.getVariableValue());
	    builder.append(",");
	    RequestManager.instance().instantiateVariable(i.getVariableName(), i.getVariableValue());
	}

	if (instantiationExist) {
	    String instantiated = builder.toString();
	    instantiated = instantiated.substring(0, instantiated.length() - 1);
	    JTextAreaLogger.instance().log(instantiated);
	} else {
	    JTextAreaLogger.instance().log("No variables instantiated");
	}

	instantiatedNow.clear();
	this.setVisible(false);
    }
}
